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:
@@ -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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>", "*")
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Web.HealthCheck.NotificationMethods;
|
||||
|
||||
namespace Umbraco.Web.HealthCheck
|
||||
{
|
||||
public interface IHealthCheckNotificationMethodsResolver
|
||||
{
|
||||
IEnumerable<IHealthCheckNotificatationMethod> NotificationMethods { get; }
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Web.HealthCheck.NotificationMethods
|
||||
{
|
||||
public interface IHealthCheckNotificatationMethod
|
||||
{
|
||||
Task SendAsync(HealthCheckResults results);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user