Added health checks

pull/3400/head
tidusjar 4 years ago
parent 483f021e29
commit 99d9ccc7dd

@ -0,0 +1,16 @@
using Microsoft.Extensions.DependencyInjection;
using System;
namespace Ombi.HealthChecks
{
public static class HealthCheckExtensions
{
public static IHealthChecksBuilder AddOmbiHealthChecks(this IHealthChecksBuilder builder)
{
builder.AddCheck<PlexHealthCheck>("Plex", tags: new string[] { "MediaServer" });
return builder;
}
}
}

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Api.Plex\Ombi.Api.Plex.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,50 @@
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models.Status;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Ombi.HealthChecks
{
public class PlexHealthCheck : IHealthCheck
{
private readonly IPlexApi _plexApi;
private readonly ISettingsService<PlexSettings> _settings;
public PlexHealthCheck(IPlexApi plexApi, ISettingsService<PlexSettings> settings)
{
_plexApi = plexApi;
_settings = settings;
}
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var settings = await _settings.GetSettingsAsync();
if (settings == null)
{
return HealthCheckResult.Healthy("Plex is not confiured.");
}
var taskResult = new List<Task<PlexStatus>>();
foreach (var server in settings.Servers)
{
taskResult.Add(_plexApi.GetStatus(server.PlexAuthToken, server.FullUri));
}
try
{
var result = await Task.WhenAll(taskResult.ToArray());
return HealthCheckResult.Healthy();
}
catch (Exception e)
{
return HealthCheckResult.Unhealthy("Could not communicate with Plex", e);
}
}
}
}

@ -110,7 +110,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.GroupMe", "Ombi.Ap
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.MusicBrainz", "Ombi.Api.MusicBrainz\Ombi.Api.MusicBrainz.csproj", "{C5C1769B-4197-4410-A160-0EEF39EDDC98}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Twilio", "Ombi.Api.Twilio\Ombi.Api.Twilio.csproj", "{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Twilio", "Ombi.Api.Twilio\Ombi.Api.Twilio.csproj", "{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.HealthChecks", "Ombi.HealthChecks\Ombi.HealthChecks.csproj", "{59D19538-0496-44EE-936E-EBBC22CF7B27}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -298,6 +300,10 @@ Global
{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Release|Any CPU.Build.0 = Release|Any CPU
{59D19538-0496-44EE-936E-EBBC22CF7B27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59D19538-0496-44EE-936E-EBBC22CF7B27}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59D19538-0496-44EE-936E-EBBC22CF7B27}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59D19538-0496-44EE-936E-EBBC22CF7B27}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -341,6 +347,7 @@ Global
{9266403C-B04D-4C0F-AC39-82F12C781949} = {9293CA11-360A-4C20-A674-B9E794431BF5}
{C5C1769B-4197-4410-A160-0EEF39EDDC98} = {9293CA11-360A-4C20-A674-B9E794431BF5}
{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3} = {9293CA11-360A-4C20-A674-B9E794431BF5}
{59D19538-0496-44EE-936E-EBBC22CF7B27} = {410F36CF-9C60-428A-B191-6FD90610991A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869}

@ -2,6 +2,7 @@
using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Newtonsoft.Json;
using Ombi.Helpers;
using Ombi.Store.Context;
@ -17,7 +18,7 @@ namespace Ombi.Extensions
public const string SqliteDatabase = "Sqlite";
public const string MySqlDatabase = "MySQL";
public static void ConfigureDatabases(this IServiceCollection services)
public static void ConfigureDatabases(this IServiceCollection services, IHealthChecksBuilder hcBuilder)
{
var configuration = GetDatabaseConfiguration();
@ -26,9 +27,11 @@ namespace Ombi.Extensions
{
case var type when type.Equals(SqliteDatabase, StringComparison.InvariantCultureIgnoreCase):
services.AddDbContext<OmbiContext, OmbiSqliteContext>(x => ConfigureSqlite(x, configuration.OmbiDatabase));
AddSqliteHealthCheck(hcBuilder, "Ombi Database", configuration.OmbiDatabase);
break;
case var type when type.Equals(MySqlDatabase, StringComparison.InvariantCultureIgnoreCase):
services.AddDbContext<OmbiContext, OmbiMySqlContext>(x => ConfigureMySql(x, configuration.OmbiDatabase));
AddMySqlHealthCheck(hcBuilder, "Ombi Database", configuration.OmbiDatabase);
break;
}
@ -36,9 +39,11 @@ namespace Ombi.Extensions
{
case var type when type.Equals(SqliteDatabase, StringComparison.InvariantCultureIgnoreCase):
services.AddDbContext<ExternalContext, ExternalSqliteContext>(x => ConfigureSqlite(x, configuration.ExternalDatabase));
AddSqliteHealthCheck(hcBuilder, "External Database", configuration.ExternalDatabase);
break;
case var type when type.Equals(MySqlDatabase, StringComparison.InvariantCultureIgnoreCase):
services.AddDbContext<ExternalContext, ExternalMySqlContext>(x => ConfigureMySql(x, configuration.ExternalDatabase));
AddMySqlHealthCheck(hcBuilder, "External Database", configuration.ExternalDatabase);
break;
}
@ -46,9 +51,11 @@ namespace Ombi.Extensions
{
case var type when type.Equals(SqliteDatabase, StringComparison.InvariantCultureIgnoreCase):
services.AddDbContext<SettingsContext, SettingsSqliteContext>(x => ConfigureSqlite(x, configuration.SettingsDatabase));
AddSqliteHealthCheck(hcBuilder, "Settings Database", configuration.SettingsDatabase);
break;
case var type when type.Equals(MySqlDatabase, StringComparison.InvariantCultureIgnoreCase):
services.AddDbContext<SettingsContext, SettingsMySqlContext>(x => ConfigureMySql(x, configuration.SettingsDatabase));
AddMySqlHealthCheck(hcBuilder, "Settings Database", configuration.SettingsDatabase);
break;
}
}
@ -62,7 +69,7 @@ namespace Ombi.Extensions
}
var databaseFileLocation = Path.Combine(i.StoragePath, "database.json");
var configuration = new DatabaseConfiguration(i.StoragePath);
if (File.Exists(databaseFileLocation))
{
@ -78,11 +85,36 @@ namespace Ombi.Extensions
return configuration;
}
private static void AddSqliteHealthCheck(IHealthChecksBuilder builder, string dbName, PerDatabaseConfiguration config)
{
if (builder != null)
{
builder.AddSqlite(
sqliteConnectionString: config.ConnectionString,
name: dbName,
failureStatus: HealthStatus.Unhealthy,
tags: new string[] { "db" });
}
}
private static void AddMySqlHealthCheck(IHealthChecksBuilder builder, string dbName, PerDatabaseConfiguration config)
{
if (builder != null)
{
builder.AddMySql(
connectionString: config.ConnectionString,
name: dbName,
failureStatus: HealthStatus.Unhealthy,
tags: new string[] { "db" }
);
}
}
public static void ConfigureSqlite(DbContextOptionsBuilder options, PerDatabaseConfiguration config)
{
SQLitePCL.Batteries.Init();
SQLitePCL.raw.sqlite3_config(raw.SQLITE_CONFIG_MULTITHREAD);
options.UseSqlite(config.ConnectionString);
}

@ -56,6 +56,10 @@
<ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.MySql" Version="3.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.Sqlite" Version="3.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI" Version="3.0.9" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="3.0.2" />
<PackageReference Include="AutoMapper" Version="6.1.1" />
<PackageReference Include="CommandLineParser" Version="2.6.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.1" />
@ -85,6 +89,7 @@
<ProjectReference Include="..\Ombi.Api.Twilio\Ombi.Api.Twilio.csproj" />
<ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj" />
<ProjectReference Include="..\Ombi.DependencyInjection\Ombi.DependencyInjection.csproj" />
<ProjectReference Include="..\Ombi.HealthChecks\Ombi.HealthChecks.csproj" />
<ProjectReference Include="..\Ombi.Hubs\Ombi.Hubs.csproj" />
<ProjectReference Include="..\Ombi.Mapping\Ombi.Mapping.csproj" />
<ProjectReference Include="..\Ombi.Schedule\Ombi.Schedule.csproj" />

@ -59,7 +59,7 @@ namespace Ombi
//CheckAndMigrate();
var services = new ServiceCollection();
services.ConfigureDatabases();
services.ConfigureDatabases(null);
using (var provider = services.BuildServiceProvider())
{
var settingsDb = provider.GetRequiredService<SettingsContext>();

@ -28,6 +28,9 @@ using Microsoft.AspNetCore.StaticFiles.Infrastructure;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using ILogger = Serilog.ILogger;
using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Ombi.HealthChecks;
namespace Ombi
{
@ -73,8 +76,13 @@ namespace Ombi
options.User.AllowedUserNameCharacters = string.Empty;
});
services.ConfigureDatabases();
services.AddHealthChecks();
var hcBuilder = services.AddHealthChecks();
hcBuilder.AddOmbiHealthChecks();
services.ConfigureDatabases(hcBuilder);
services.AddHealthChecksUI(setupSettings: setup =>
{
setup.AddHealthCheckEndpoint("Ombi", "http://localhost:3577/healthz");
});
services.AddMemoryCache();
services.AddJwtAuthentication(Configuration);
@ -205,17 +213,20 @@ namespace Ombi
endpoints.MapControllers();
endpoints.MapHub<NotificationHub>("/hubs/notification");
endpoints.MapHealthChecks("/health");
endpoints.MapHealthChecks("/healthz", new HealthCheckOptions
{
Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
endpoints.MapHealthChecksUI();
});
app.UseSpa(spa =>
{
#if DEBUG
//if (env.IsDevelopment())
//{
spa.Options.SourcePath = "ClientApp";
spa.UseProxyToSpaDevelopmentServer("http://localhost:3578");
//}
#endif
//#if DEBUG
// spa.Options.SourcePath = "ClientApp";
// spa.UseProxyToSpaDevelopmentServer("http://localhost:3578");
//#endif
});
}

Binary file not shown.
Loading…
Cancel
Save