Amended registration of health check scheduled notifiers (email and Slack) to use a resolver method and allow others to be added without modifying core

This commit is contained in:
AndyButland
2017-06-18 16:41:46 +02:00
parent 01a2ba8ad6
commit 9f68bd4e52
21 changed files with 492 additions and 170 deletions

View File

@@ -1,28 +0,0 @@
using System.Configuration;
namespace Umbraco.Core.Configuration.HealthChecks
{
public abstract class BaseNotificationMethodElement : ConfigurationElement
{
private const string VERBOSITY_KEY = "verbosity";
private const string FAILUREONLY_KEY = "failureOnly";
[ConfigurationProperty(VERBOSITY_KEY, IsRequired = true)]
public HealthCheckNotificationVerbosity Verbosity
{
get
{
return ((HealthCheckNotificationVerbosity)(base[VERBOSITY_KEY]));
}
}
[ConfigurationProperty(FAILUREONLY_KEY, IsRequired = true)]
public bool FailureOnly
{
get
{
return ((bool)(base[FAILUREONLY_KEY]));
}
}
}
}

View File

@@ -1,28 +0,0 @@
using System.Configuration;
namespace Umbraco.Core.Configuration.HealthChecks
{
public class EmailSettingsElement : BaseNotificationMethodElement
{
private const string RECIPIENT_EMAIL_KEY = "recipientEmail";
private const string SUBJECT_KEY = "subject";
[ConfigurationProperty(RECIPIENT_EMAIL_KEY, IsRequired = true)]
public string RecipientEmail
{
get
{
return ((string)(base[RECIPIENT_EMAIL_KEY]));
}
}
[ConfigurationProperty(SUBJECT_KEY, IsRequired = true)]
public string Subject
{
get
{
return ((string)(base[SUBJECT_KEY]));
}
}
}
}

View File

@@ -11,16 +11,15 @@ namespace Umbraco.Core.Configuration.HealthChecks
private const string ENABLED_KEY = "enabled";
private const string FIRST_RUN_TIME_KEY = "firstRunTime";
private const string PERIOD_KEY = "periodInHours";
private const string NOTIFICATION_METHODS_KEY = "notificationMethods";
private const string DISABLED_CHECKS_KEY = "disabledChecks";
private const string EMAIL_SETTINGS_KEY = "emailSettings";
private const string SLACK_SETTINGS_KEY = "slackSettings";
[ConfigurationProperty(ENABLED_KEY, IsRequired = true)]
public bool Enabled
{
get
{
return ((bool)(base[ENABLED_KEY]));
return (bool)base[ENABLED_KEY];
}
}
@@ -29,7 +28,7 @@ namespace Umbraco.Core.Configuration.HealthChecks
{
get
{
return ((string)(base[FIRST_RUN_TIME_KEY]));
return (string)base[FIRST_RUN_TIME_KEY];
}
}
@@ -38,34 +37,25 @@ namespace Umbraco.Core.Configuration.HealthChecks
{
get
{
return ((int)(base[PERIOD_KEY]));
return (int)base[PERIOD_KEY];
}
}
[ConfigurationProperty(DISABLED_CHECKS_KEY, IsDefaultCollection = true, IsRequired = false)]
[ConfigurationProperty(NOTIFICATION_METHODS_KEY, IsDefaultCollection = true, IsRequired = false)]
public NotificationMethodsElementCollection NotificationMethods
{
get
{
return (NotificationMethodsElementCollection)base[NOTIFICATION_METHODS_KEY];
}
}
[ConfigurationProperty(DISABLED_CHECKS_KEY, IsDefaultCollection = false, IsRequired = false)]
public DisabledHealthChecksElementCollection DisabledChecks
{
get
{
return ((DisabledHealthChecksElementCollection)(base[DISABLED_CHECKS_KEY]));
}
}
[ConfigurationProperty(EMAIL_SETTINGS_KEY, IsDefaultCollection = true, IsRequired = false)]
public EmailSettingsElement EmailSettings
{
get
{
return ((EmailSettingsElement)(base[EMAIL_SETTINGS_KEY]));
}
}
[ConfigurationProperty(SLACK_SETTINGS_KEY, IsDefaultCollection = true, IsRequired = false)]
public SlackSettingsElement SlackSettings
{
get
{
return ((SlackSettingsElement)(base[SLACK_SETTINGS_KEY]));
return (DisabledHealthChecksElementCollection)base[DISABLED_CHECKS_KEY];
}
}
}

View File

@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
namespace Umbraco.Core.Configuration.HealthChecks
{
public class NotificationMethodElement : ConfigurationElement
{
private const string ALIAS_KEY = "alias";
private const string ENABLED_KEY = "enabled";
private const string VERBOSITY_KEY = "verbosity";
private const string FAILUREONLY_KEY = "failureOnly";
private const string SETTINGS_KEY = "settings";
[ConfigurationProperty(ALIAS_KEY, IsKey = true, IsRequired = true)]
public string Alias
{
get
{
return (string)base[ALIAS_KEY];
}
}
[ConfigurationProperty(ENABLED_KEY, IsKey = true, IsRequired = true)]
public bool Enabled
{
get
{
return (bool)base[ENABLED_KEY];
}
}
[ConfigurationProperty(VERBOSITY_KEY, IsRequired = true)]
public HealthCheckNotificationVerbosity Verbosity
{
get
{
return (HealthCheckNotificationVerbosity)base[VERBOSITY_KEY];
}
}
[ConfigurationProperty(FAILUREONLY_KEY, IsRequired = false)]
public bool FailureOnly
{
get
{
return (bool)base[FAILUREONLY_KEY];
}
}
[ConfigurationProperty(SETTINGS_KEY, IsDefaultCollection = true, IsRequired = false)]
public NotificationMethodSettingsElementCollection Settings
{
get
{
return (NotificationMethodSettingsElementCollection)base[SETTINGS_KEY];
}
}
}
}

View File

@@ -0,0 +1,28 @@
using System.Configuration;
namespace Umbraco.Core.Configuration.HealthChecks
{
public class NotificationMethodSettingsElement : ConfigurationElement
{
private const string KEY_KEY = "key";
private const string VALUE_KEY = "value";
[ConfigurationProperty(KEY_KEY, IsKey = true, IsRequired = true)]
public string Key
{
get
{
return (string)base[KEY_KEY];
}
}
[ConfigurationProperty(VALUE_KEY, IsRequired = true)]
public string Value
{
get
{
return (string)base[VALUE_KEY];
}
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Configuration;
namespace Umbraco.Core.Configuration.HealthChecks
{
[ConfigurationCollection(typeof(NotificationMethodSettingsElement), AddItemName = "add")]
public class NotificationMethodSettingsElementCollection : ConfigurationElementCollection, IEnumerable<NotificationMethodSettingsElement>
{
protected override ConfigurationElement CreateNewElement()
{
return new NotificationMethodSettingsElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((NotificationMethodSettingsElement)(element)).Key;
}
new public NotificationMethodSettingsElement this[string key]
{
get
{
return (NotificationMethodSettingsElement)BaseGet(key);
}
}
IEnumerator<NotificationMethodSettingsElement> IEnumerable<NotificationMethodSettingsElement>.GetEnumerator()
{
for (var i = 0; i < Count; i++)
{
yield return BaseGet(i) as NotificationMethodSettingsElement;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Configuration;
namespace Umbraco.Core.Configuration.HealthChecks
{
[ConfigurationCollection(typeof(NotificationMethodElement), AddItemName = "notificationMethod")]
public class NotificationMethodsElementCollection : ConfigurationElementCollection, IEnumerable<NotificationMethodElement>
{
protected override ConfigurationElement CreateNewElement()
{
return new NotificationMethodElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((NotificationMethodElement)(element)).Alias;
}
new public NotificationMethodElement this[string key]
{
get
{
return (NotificationMethodElement)BaseGet(key);
}
}
IEnumerator<NotificationMethodElement> IEnumerable<NotificationMethodElement>.GetEnumerator()
{
for (var i = 0; i < Count; i++)
{
yield return BaseGet(i) as NotificationMethodElement;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -1,38 +0,0 @@
using System.Configuration;
namespace Umbraco.Core.Configuration.HealthChecks
{
public class SlackSettingsElement : BaseNotificationMethodElement
{
private const string WEBHOOKURL_KEY = "webHookUrl";
private const string CHANNEL_KEY = "channel";
private const string USERNAME_KEY = "username";
[ConfigurationProperty(WEBHOOKURL_KEY, IsRequired = true)]
public string WebHookUrl
{
get
{
return ((string)(base[WEBHOOKURL_KEY]));
}
}
[ConfigurationProperty(CHANNEL_KEY, IsRequired = true)]
public string Channel
{
get
{
return ((string)(base[CHANNEL_KEY]));
}
}
[ConfigurationProperty(USERNAME_KEY, IsRequired = true)]
public string UserName
{
get
{
return ((string)(base[USERNAME_KEY]));
}
}
}
}

View File

@@ -218,11 +218,12 @@
<Compile Include="Configuration\Dashboard\SectionElement.cs" />
<Compile Include="Configuration\Dashboard\TabCollection.cs" />
<Compile Include="Configuration\Dashboard\TabElement.cs" />
<Compile Include="Configuration\HealthChecks\BaseNotificationMethodElement.cs" />
<Compile Include="Configuration\HealthChecks\NotificationMethodSettingsElement.cs" />
<Compile Include="Configuration\HealthChecks\NotificationMethodElement.cs" />
<Compile Include="Configuration\HealthChecks\NotificationMethodSettingsElementCollection.cs" />
<Compile Include="Configuration\HealthChecks\NotificationMethodsElementCollection.cs" />
<Compile Include="Configuration\HealthChecks\HealthCheckNotificationVerbosity.cs" />
<Compile Include="Configuration\HealthChecks\SlackSettingsElement.cs" />
<Compile Include="Configuration\HealthChecks\HealthCheckNotificationSettingsElement.cs" />
<Compile Include="Configuration\HealthChecks\EmailSettingsElement.cs" />
<Compile Include="Configuration\HealthChecks\DisabledHealthCheckElement.cs" />
<Compile Include="Configuration\FileSystemProviderElement.cs" />
<Compile Include="Configuration\HealthChecks\DisabledHealthChecksElementCollection.cs" />

View File

@@ -11,9 +11,22 @@ https://our.umbraco.org/documentation/reference/config/healthchecks
<disabledChecks>
<!--<check id="1B5D221B-CE99-4193-97CB-5F3261EC73DF" disabledOn="" disabledBy="0" />-->
</disabledChecks>
<notificationSettings enabled="true" firstRunTime="" periodInHours="24" >
<emailSettings recipientEmail="" subject="Umbraco Health Check Notifier" verbosity="Summary" />
<slackSettings webHookUrl="" channel="#test" username="Umbraco Health Check Notifier" verbosity="Detailed" />
<notificationSettings enabled="false" firstRunTime="" periodInHours="24">
<notificationMethods>
<notificationMethod alias="email" enabled="false" verbosity="Summary">
<settings>
<add key="recipientEmail" value="" />
<add key="subject" value="Umbraco Health Check Status" />
</settings>
</notificationMethod>
<notificationMethod alias="slack" enabled="false" verbosity="Summary">
<settings>
<add key="webHookUrl" value="" />
<add key="channel" value="#test" />
<add key="username" value="Umbraco Health Check Status" />
</settings>
</notificationMethod>
</notificationMethods>
<disabledChecks>
<!--<check id="EB66BB3B-1BCD-4314-9531-9DA2C1D6D9A7" disabledOn="" disabledBy="0" />-->
</disabledChecks>

View File

@@ -0,0 +1,18 @@
using System;
namespace Umbraco.Web.HealthCheck
{
/// <summary>
/// Metadata attribute for health check notification methods
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class HealthCheckNotificationMethodAttribute : Attribute
{
public HealthCheckNotificationMethodAttribute(string alias)
{
Alias = alias;
}
public string Alias { get; private set; }
}
}

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Web.HealthCheck.NotificationMethods;
namespace Umbraco.Web.HealthCheck
{
using System.Configuration;
using System.Reflection;
using Umbraco.Core.Configuration.HealthChecks;
/// <summary>
/// Resolves all health check instances
/// </summary>
/// <remarks>
/// Each instance scoped to the lifespan of the http request
/// </remarks>
internal class HealthCheckNotificationMethodResolver : LazyManyObjectsResolverBase<HealthCheckNotificationMethodResolver, IHealthCheckNotificatationMethod>, IHealthCheckNotificationMethodsResolver
{
public HealthCheckNotificationMethodResolver(ILogger logger, Func<IEnumerable<Type>> lazyTypeList)
: base(new HealthCheckNotificationMethodServiceProvider(), logger, lazyTypeList, ObjectLifetimeScope.Application)
{
}
/// <summary>
/// Returns all health check notification method instances
/// </summary>
public IEnumerable<IHealthCheckNotificatationMethod> NotificationMethods
{
get { return Values; }
}
/// <summary>
/// This will ctor the IHealthCheckNotificatationMethod instances
/// </summary>
private class HealthCheckNotificationMethodServiceProvider : IServiceProvider
{
public object GetService(Type serviceType)
{
var ctor = serviceType.GetConstructors().FirstOrDefault();
if (ctor == null)
{
return null;
}
// Load attribute from type in order to find alias for notification method
var attribute = serviceType.GetCustomAttributes(typeof(HealthCheckNotificationMethodAttribute), true)
.FirstOrDefault() as HealthCheckNotificationMethodAttribute;
if (attribute == null)
{
return null;
}
// Using alias, get related configuration
var healthCheckConfig = (HealthChecksSection)ConfigurationManager.GetSection("umbracoConfiguration/HealthChecks");
var notificationMethods = healthCheckConfig.NotificationSettings.NotificationMethods;
var notificationMethod = notificationMethods[attribute.Alias];
if (notificationMethod == null)
{
return null;
}
// Create array for constructor paramenters. Will consists of common ones that all notification methods have as well
// as those specific to this particular notification method.
var baseType = typeof(NotificationMethodBase);
var baseTypeCtor = baseType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).First();
var baseTypeCtorParamNames = baseTypeCtor.GetParameters().Select(x => x.Name);
var ctorParams = new List<object> { notificationMethod.Enabled, notificationMethod.FailureOnly, notificationMethod.Verbosity };
ctorParams.AddRange(ctor.GetParameters()
.Where(x => baseTypeCtorParamNames.Contains(x.Name) == false)
.Select(x => notificationMethod.Settings[x.Name].Value));
// Instantiate the type with the constructor parameters
return Activator.CreateInstance(serviceType, ctorParams.ToArray());
}
}
}
}

View File

@@ -8,12 +8,12 @@ using Umbraco.Core.Logging;
namespace Umbraco.Web.HealthCheck
{
internal class HealthCheckResults
public class HealthCheckResults
{
private readonly Dictionary<string, IEnumerable<HealthCheckStatus>> _results;
internal readonly bool AllChecksSuccessful;
internal HealthCheckResults(IEnumerable<HealthCheck> checks)
public HealthCheckResults(IEnumerable<HealthCheck> checks)
{
_results = checks.ToDictionary(
t => t.Name,
@@ -49,7 +49,7 @@ namespace Umbraco.Web.HealthCheck
}
}
internal void LogResults()
public void LogResults()
{
LogHelper.Info<HealthCheckResults>("Scheduled health check results:");
foreach (var result in _results)
@@ -73,7 +73,7 @@ namespace Umbraco.Web.HealthCheck
}
}
internal string ResultsAsMarkDown(HealthCheckNotificationVerbosity verbosity, bool slackMarkDown = false)
public string ResultsAsMarkDown(HealthCheckNotificationVerbosity verbosity, bool slackMarkDown = false)
{
var newItem = "- ";
if (slackMarkDown)
@@ -121,7 +121,7 @@ namespace Umbraco.Web.HealthCheck
return sb.ToString();
}
internal string ResultsAsHtml(HealthCheckNotificationVerbosity verbosity)
public string ResultsAsHtml(HealthCheckNotificationVerbosity verbosity)
{
var mark = new Markdown();
var html = mark.Transform(ResultsAsMarkDown(verbosity));
@@ -151,6 +151,7 @@ namespace Umbraco.Web.HealthCheck
.Replace("<em>", "_")
.Replace("</em>", "_");
}
return html.Replace("<strong>", "**")
.Replace("</strong>", "**")
.Replace("<em>", "*")

View File

@@ -0,0 +1,10 @@
using System.Collections.Generic;
using Umbraco.Web.HealthCheck.NotificationMethods;
namespace Umbraco.Web.HealthCheck
{
public interface IHealthCheckNotificationMethodsResolver
{
IEnumerable<IHealthCheckNotificatationMethod> NotificationMethods { get; }
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Net.Mail;
using System.Threading.Tasks;
using Umbraco.Core.Configuration.HealthChecks;
namespace Umbraco.Web.HealthCheck.NotificationMethods
{
[HealthCheckNotificationMethod("email")]
public class EmailNotificationMethod : NotificationMethodBase, IHealthCheckNotificatationMethod
{
public EmailNotificationMethod(bool enabled, bool failureOnly, HealthCheckNotificationVerbosity verbosity,
string recipientEmail, string subject)
: base(enabled, failureOnly, verbosity)
{
RecipientEmail = recipientEmail;
Subject = subject;
Verbosity = verbosity;
}
public string RecipientEmail { get; set; }
public string Subject { get; set; }
public async Task SendAsync(HealthCheckResults results)
{
if (ShouldSend(results) == false)
{
return;
}
if (string.IsNullOrEmpty(RecipientEmail))
{
return;
}
using (var client = new SmtpClient())
using (var mailMessage = new MailMessage())
{
mailMessage.To.Add(RecipientEmail);
mailMessage.Body =
string.Format(
"<html><body><p>Results of the scheduled Umbraco Health Checks run on {0} at {1} are as follows:</p>{2}</body></html>",
DateTime.Now.ToShortDateString(),
DateTime.Now.ToShortTimeString(),
results.ResultsAsHtml(Verbosity));
mailMessage.Subject = string.IsNullOrEmpty(Subject) ? "Umbraco Health Check Status" : Subject;
mailMessage.IsBodyHtml = true;
await client.SendMailAsync(mailMessage);
}
}
}
}

View File

@@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Umbraco.Web.HealthCheck.NotificationMethods
{
public interface IHealthCheckNotificatationMethod
{
Task SendAsync(HealthCheckResults results);
}
}

View File

@@ -0,0 +1,35 @@
using Umbraco.Core.Configuration.HealthChecks;
namespace Umbraco.Web.HealthCheck.NotificationMethods
{
public abstract class NotificationMethodBase
{
protected NotificationMethodBase(bool enabled, bool failureOnly, HealthCheckNotificationVerbosity verbosity)
{
Enabled = enabled;
FailureOnly = failureOnly;
Verbosity = verbosity;
}
public bool Enabled { get; set; }
public bool FailureOnly { get; set; }
public HealthCheckNotificationVerbosity Verbosity { get; set; }
protected bool ShouldSend(HealthCheckResults results)
{
if (Enabled == false)
{
return false;
}
if (FailureOnly && results.AllChecksSuccessful)
{
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,55 @@
using System.Threading.Tasks;
using Slack.Webhooks;
using Umbraco.Core.Configuration.HealthChecks;
namespace Umbraco.Web.HealthCheck.NotificationMethods
{
[HealthCheckNotificationMethod("slack")]
public class SlackNotificationMethod : NotificationMethodBase, IHealthCheckNotificatationMethod
{
public SlackNotificationMethod(bool enabled, bool failureOnly, HealthCheckNotificationVerbosity verbosity,
string webHookUrl, string channel, string username)
: base(enabled, failureOnly, verbosity)
{
WebHookUrl = webHookUrl;
Channel = channel;
Username = username;
}
public string WebHookUrl { get; set; }
public string Channel { get; set; }
public string Username { get; set; }
public async Task SendAsync(HealthCheckResults results)
{
if (ShouldSend(results) == false)
{
return;
}
if (string.IsNullOrEmpty(WebHookUrl) || string.IsNullOrEmpty(Channel) || string.IsNullOrEmpty(Username))
{
return;
}
var slackClient = new SlackClient(WebHookUrl);
var icon = Emoji.Warning;
if (results.AllChecksSuccessful)
{
icon = Emoji.WhiteCheckMark;
}
var slackMessage = new SlackMessage
{
Channel = Channel,
Text = results.ResultsAsMarkDown(Verbosity, true),
IconEmoji = icon,
Username = Username
};
await slackClient.PostAsync(slackMessage);
}
}
}

View File

@@ -69,47 +69,11 @@ namespace Umbraco.Web.Scheduling
var results = new HealthCheckResults(checks);
results.LogResults();
// Send to email address if configured observing if the configuration is set to only notify if there are any failures
var emailNotificationSettings = healthCheckConfig.NotificationSettings.EmailSettings;
if (emailNotificationSettings != null && string.IsNullOrEmpty(emailNotificationSettings.RecipientEmail) == false
&& (emailNotificationSettings.FailureOnly == false || emailNotificationSettings.FailureOnly && results.AllChecksSuccessful == false))
// Send using registered notification methods
var registeredNotificationMethods = HealthCheckNotificationMethodResolver.Current.NotificationMethods;
foreach (var notificationMethod in registeredNotificationMethods)
{
using (var client = new SmtpClient())
using (var mailMessage = new MailMessage())
{
mailMessage.To.Add(emailNotificationSettings.RecipientEmail);
mailMessage.Body =
string.Format(
"<html><body><p>Results of the scheduled Umbraco Health Checks run on {0} at {1} are as follows:</p>{2}</body></html>",
DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString(),
results.ResultsAsHtml(emailNotificationSettings.Verbosity));
mailMessage.Subject = emailNotificationSettings.Subject;
mailMessage.IsBodyHtml = true;
await client.SendMailAsync(mailMessage);
}
}
// Send Slack incoming webhook if configured observing if the configuration is set to only notify if there are any failures
var slackNotificationSettings = healthCheckConfig.NotificationSettings.SlackSettings;
if (slackNotificationSettings != null && string.IsNullOrEmpty(slackNotificationSettings.WebHookUrl) == false && (slackNotificationSettings.FailureOnly == false || slackNotificationSettings.FailureOnly && results.AllChecksSuccessful == false))
{
var slackClient = new SlackClient(slackNotificationSettings.WebHookUrl);
var icon = Emoji.Warning;
if (results.AllChecksSuccessful)
{
icon = Emoji.WhiteCheckMark;
}
var slackMessage = new SlackMessage
{
Channel = slackNotificationSettings.Channel,
Text = results.ResultsAsMarkDown(slackNotificationSettings.Verbosity, true),
IconEmoji = icon,
Username = slackNotificationSettings.UserName
};
slackClient.Post(slackMessage);
await notificationMethod.SendAsync(results);
}
}

View File

@@ -362,16 +362,23 @@
<Compile Include="HealthCheck\Checks\Security\ExcessiveHeadersCheck.cs" />
<Compile Include="HealthCheck\Checks\Security\ClickJackingCheck.cs" />
<Compile Include="HealthCheck\HealthCheckAction.cs" />
<Compile Include="HealthCheck\HealthCheckNotificationMethodAttribute.cs" />
<Compile Include="HealthCheck\HealthCheckAttribute.cs" />
<Compile Include="HealthCheck\HealthCheckContext.cs" />
<Compile Include="HealthCheck\HealthCheckController.cs" />
<Compile Include="HealthCheck\HealthCheckGroup.cs" />
<Compile Include="HealthCheck\HealthCheckNotificationMethodResolver.cs" />
<Compile Include="HealthCheck\HealthCheckResolver.cs" />
<Compile Include="HealthCheck\HealthCheck.cs" />
<Compile Include="HealthCheck\HealthCheckResults.cs" />
<Compile Include="HealthCheck\HealthCheckStatus.cs" />
<Compile Include="HealthCheck\Checks\Security\HttpsCheck.cs" />
<Compile Include="HealthCheck\IHealthCheckResolver.cs" />
<Compile Include="HealthCheck\IHealthCheckNotificationMethodsResolver.cs" />
<Compile Include="HealthCheck\NotificationMethods\NotificationMethodBase.cs" />
<Compile Include="HealthCheck\NotificationMethods\SlackNotificationMethod.cs" />
<Compile Include="HealthCheck\NotificationMethods\EmailNotificationMethod.cs" />
<Compile Include="HealthCheck\NotificationMethods\IHealthCheckNotificatationMethod.cs" />
<Compile Include="HealthCheck\StatusResultType.cs" />
<Compile Include="HealthCheck\Checks\DataIntegrity\XmlDataIntegrityHealthCheck.cs" />
<Compile Include="IHttpContextAccessor.cs" />

View File

@@ -544,6 +544,8 @@ namespace Umbraco.Web
HealthCheckResolver.Current = new HealthCheckResolver(LoggerResolver.Current.Logger,
() => PluginManager.ResolveTypes<HealthCheck.HealthCheck>());
HealthCheckNotificationMethodResolver.Current = new HealthCheckNotificationMethodResolver(LoggerResolver.Current.Logger,
() => PluginManager.ResolveTypes<HealthCheck.NotificationMethods.IHealthCheckNotificatationMethod>());
}
/// <summary>