Netcore: Health check notifier hosted service (#9295)

* Implemented health check notifier as a hosted service.
Added validation to health check settings.

* Registered health check notifier as a hosted service.
Modified health check nested settings to use concrete classes to align with other configuration models.

* Resolved issues with email sending using development server.

* PR review comments and fixed failing unit test.

* Changed period and delay millisecond and hourly values to TimeSpans.
Changed configuration of first run time for health check notifications to use H:mm format.

* Set up SecureSocketOptions as a locally defined enum.

* Tightened up time format validation to verify input is an actual time (with hours and minutes only) and not a timespan.

* Aligned naming and namespace of health check configuration related classes with other configuration classes.

* Created constants for hex colors used in formatting health check results as HTML.

* Revert "Tightened up time format validation to verify input is an actual time (with hours and minutes only) and not a timespan."

This reverts commit f9bb8a7a825bcb58146879f18b47922e09453e2d.

* Renamed method to be clear validation is of a TimeSpan and not a time.

Co-authored-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
Andy Butland
2020-10-30 13:56:13 +01:00
committed by GitHub
parent 4ae329589a
commit bdb8f34da3
31 changed files with 636 additions and 248 deletions

View File

@@ -12,8 +12,6 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog;
using Serilog.Extensions.Hosting;
using Serilog.Extensions.Logging;
using Umbraco.Composing;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
@@ -26,97 +24,17 @@ using Umbraco.Core.Logging.Serilog;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Runtime;
using Umbraco.Infrastructure.HostedServices;
using Umbraco.Web.Common.AspNetCore;
using Umbraco.Web.Common.Profiler;
using ConnectionStrings = Umbraco.Core.Configuration.Models.ConnectionStrings;
using CoreDebugSettings = Umbraco.Core.Configuration.Models.CoreDebugSettings;
using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace Umbraco.Extensions
{
public static class UmbracoCoreServiceCollectionExtensions
{
/// <summary>
/// Adds SqlCe support for Umbraco
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddUmbracoSqlCeSupport(this IServiceCollection services)
{
try
{
var binFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (binFolder != null)
{
var dllPath = Path.Combine(binFolder, "Umbraco.Persistance.SqlCe.dll");
var umbSqlCeAssembly = Assembly.LoadFrom(dllPath);
var sqlCeSyntaxProviderType = umbSqlCeAssembly.GetType("Umbraco.Persistance.SqlCe.SqlCeSyntaxProvider");
var sqlCeBulkSqlInsertProviderType = umbSqlCeAssembly.GetType("Umbraco.Persistance.SqlCe.SqlCeBulkSqlInsertProvider");
var sqlCeEmbeddedDatabaseCreatorType = umbSqlCeAssembly.GetType("Umbraco.Persistance.SqlCe.SqlCeEmbeddedDatabaseCreator");
if (!(sqlCeSyntaxProviderType is null || sqlCeBulkSqlInsertProviderType is null || sqlCeEmbeddedDatabaseCreatorType is null))
{
services.AddSingleton(typeof(ISqlSyntaxProvider), sqlCeSyntaxProviderType);
services.AddSingleton(typeof(IBulkSqlInsertProvider), sqlCeBulkSqlInsertProviderType);
services.AddSingleton(typeof(IEmbeddedDatabaseCreator), sqlCeEmbeddedDatabaseCreatorType);
}
var sqlCeAssembly = Assembly.LoadFrom(Path.Combine(binFolder, "System.Data.SqlServerCe.dll"));
var sqlCe = sqlCeAssembly.GetType("System.Data.SqlServerCe.SqlCeProviderFactory");
if (!(sqlCe is null))
{
DbProviderFactories.RegisterFactory(Core.Constants.DbProviderNames.SqlCe, sqlCe);
}
}
}
catch
{
// Ignore if SqlCE is not available
}
return services;
}
/// <summary>
/// Adds Sql Server support for Umbraco
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddUmbracoSqlServerSupport(this IServiceCollection services)
{
DbProviderFactories.RegisterFactory(Core.Constants.DbProviderNames.SqlServer, SqlClientFactory.Instance);
services.AddSingleton<ISqlSyntaxProvider, SqlServerSyntaxProvider>();
services.AddSingleton<IBulkSqlInsertProvider, SqlServerBulkSqlInsertProvider>();
services.AddSingleton<IEmbeddedDatabaseCreator, NoopEmbeddedDatabaseCreator>();
return services;
}
/// <summary>
/// Adds the Umbraco Back Core requirements
/// </summary>
/// <param name="services"></param>
/// <param name="webHostEnvironment"></param>
/// <param name="umbContainer"></param>
/// <param name="entryAssembly"></param>
/// <param name="appCaches"></param>
/// <param name="loggingConfiguration"></param>
/// <param name="factory"></param>
/// <param name="configuration"></param>
/// <param name="httpContextAccessor"></param>
/// <returns></returns>
public static IServiceCollection AddUmbracoCore(this IServiceCollection services,
IWebHostEnvironment webHostEnvironment,
Assembly entryAssembly,
AppCaches appCaches,
ILoggingConfiguration loggingConfiguration,
IConfiguration configuration)
=> services.AddUmbracoCore(webHostEnvironment, entryAssembly, appCaches, loggingConfiguration, configuration, GetCoreRuntime);
/// <summary>
/// Adds the Umbraco Configuration requirements
/// </summary>
@@ -127,10 +45,13 @@ namespace Umbraco.Extensions
{
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
// Register configuration validators.
services.AddSingleton<IValidateOptions<ContentSettings>, ContentSettingsValidator>();
services.AddSingleton<IValidateOptions<GlobalSettings>, GlobalSettingsValidator>();
services.AddSingleton<IValidateOptions<HealthChecksSettings>, HealthChecksSettingsValidator >();
services.AddSingleton<IValidateOptions<RequestHandlerSettings>, RequestHandlerSettingsValidator>();
// Register configuration sections.
services.Configure<ActiveDirectorySettings>(configuration.GetSection(Constants.Configuration.ConfigActiveDirectory));
services.Configure<ConnectionStrings>(configuration.GetSection("ConnectionStrings"), o => o.BindNonPublicProperties = true);
services.Configure<ContentSettings>(configuration.GetSection(Constants.Configuration.ConfigContent));
@@ -157,6 +78,27 @@ namespace Umbraco.Extensions
return services;
}
/// <summary>
/// Adds the Umbraco Back Core requirements
/// </summary>
/// <param name="services"></param>
/// <param name="webHostEnvironment"></param>
/// <param name="umbContainer"></param>
/// <param name="entryAssembly"></param>
/// <param name="appCaches"></param>
/// <param name="loggingConfiguration"></param>
/// <param name="factory"></param>
/// <param name="configuration"></param>
/// <param name="httpContextAccessor"></param>
/// <returns></returns>
public static IServiceCollection AddUmbracoCore(this IServiceCollection services,
IWebHostEnvironment webHostEnvironment,
Assembly entryAssembly,
AppCaches appCaches,
ILoggingConfiguration loggingConfiguration,
IConfiguration configuration)
=> services.AddUmbracoCore(webHostEnvironment, entryAssembly, appCaches, loggingConfiguration, configuration, GetCoreRuntime);
/// <summary>
/// Adds the Umbraco Back Core requirements
/// </summary>
@@ -284,6 +226,77 @@ namespace Umbraco.Extensions
return services;
}
/// <summary>
/// Adds SqlCe support for Umbraco
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
private static IServiceCollection AddUmbracoSqlCeSupport(this IServiceCollection services)
{
try
{
var binFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (binFolder != null)
{
var dllPath = Path.Combine(binFolder, "Umbraco.Persistance.SqlCe.dll");
var umbSqlCeAssembly = Assembly.LoadFrom(dllPath);
var sqlCeSyntaxProviderType = umbSqlCeAssembly.GetType("Umbraco.Persistance.SqlCe.SqlCeSyntaxProvider");
var sqlCeBulkSqlInsertProviderType = umbSqlCeAssembly.GetType("Umbraco.Persistance.SqlCe.SqlCeBulkSqlInsertProvider");
var sqlCeEmbeddedDatabaseCreatorType = umbSqlCeAssembly.GetType("Umbraco.Persistance.SqlCe.SqlCeEmbeddedDatabaseCreator");
if (!(sqlCeSyntaxProviderType is null || sqlCeBulkSqlInsertProviderType is null || sqlCeEmbeddedDatabaseCreatorType is null))
{
services.AddSingleton(typeof(ISqlSyntaxProvider), sqlCeSyntaxProviderType);
services.AddSingleton(typeof(IBulkSqlInsertProvider), sqlCeBulkSqlInsertProviderType);
services.AddSingleton(typeof(IEmbeddedDatabaseCreator), sqlCeEmbeddedDatabaseCreatorType);
}
var sqlCeAssembly = Assembly.LoadFrom(Path.Combine(binFolder, "System.Data.SqlServerCe.dll"));
var sqlCe = sqlCeAssembly.GetType("System.Data.SqlServerCe.SqlCeProviderFactory");
if (!(sqlCe is null))
{
DbProviderFactories.RegisterFactory(Core.Constants.DbProviderNames.SqlCe, sqlCe);
}
}
}
catch
{
// Ignore if SqlCE is not available
}
return services;
}
/// <summary>
/// Adds Sql Server support for Umbraco
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddUmbracoSqlServerSupport(this IServiceCollection services)
{
DbProviderFactories.RegisterFactory(Core.Constants.DbProviderNames.SqlServer, SqlClientFactory.Instance);
services.AddSingleton<ISqlSyntaxProvider, SqlServerSyntaxProvider>();
services.AddSingleton<IBulkSqlInsertProvider, SqlServerBulkSqlInsertProvider>();
services.AddSingleton<IEmbeddedDatabaseCreator, NoopEmbeddedDatabaseCreator>();
return services;
}
/// <summary>
/// Adds hosted services for Umbraco.
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddUmbracoHostedServices(this IServiceCollection services)
{
services.AddHostedService<HealthCheckNotifier>();
return services;
}
private static ITypeFinder CreateTypeFinder(ILoggerFactory loggerFactory, IProfiler profiler, IWebHostEnvironment webHostEnvironment, Assembly entryAssembly, IOptionsMonitor<TypeFinderSettings> typeFinderSettings)
{
var runtimeHashPaths = new RuntimeHashPaths();
@@ -355,7 +368,7 @@ namespace Umbraco.Extensions
/// <param name="hostingEnvironment"></param>
private static void AddLogger(
IServiceCollection services,
Core.Hosting.IHostingEnvironment hostingEnvironment,
IHostingEnvironment hostingEnvironment,
ILoggingConfiguration loggingConfiguration,
IConfiguration configuration)
{