Umbraco 8 has a Health Check function that periodically checks elements of your website for things such as macro errors, logging its findings to the Health Check dashboard in your Umbraco back office. Optionally the same report can be sent to an email address.
The following are the simple steps for how to create a custom health check for an Umbraco 8 website:
- Create a Custom Class that inherits from the Umbraco.Web.HealthCheck class.
- Add custom checks to your class and return a HealthCheckStatus class as a return value.
- Re-deploy your Umbraco 8 website.
Setting up A Custom Umbraco Health Check For a Website
Our use-case was for a simple up-time Umbraco health check alert to identify website pages that do not return a http 200 response during a site crawl. They say a code example speaks a thousand words, so this is our basic up-time Umbraco Health Check class:
using System; using System.Collections.Generic; using System.Net; using System.Net.Http; using Website; namespace Umbraco.Web.HealthCheck.Checks.Services { /// /// Custom Site Crawl Health Check /// [HealthCheck( "eddb42dc-2767-4aa6-9620-e04e210357f9", // Create a unique GUID "Site Crawl", // The name of your check Description = "Checks all pages are responding with a http200.", // A description of your check Group = "Custom")] // The name of the group you want to place your check in public class SiteCrawlCheck : HealthCheck { /// /// Site Crawl Check Constructor /// public SiteCrawlCheck() { } /// /// Get the status for this health check /// /// Health Check Status public override IEnumerable GetStatus() { return new[] { CheckSiteCrawl() }; } /// /// Executes the action and returns it's status /// ///Health Check Action /// public override HealthCheckStatus ExecuteAction(HealthCheckAction action) { throw new InvalidOperationException("SiteCrawlCheck has no executable actions"); } /// /// Call Site Crawl Check Endpoint /// /// Health Check Status private HealthCheckStatus CheckSiteCrawl() { HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; using (var httpClient = new HttpClient()) { try { httpStatusCode = httpClient.GetAsync($"{App.Settings.TLD}/crawl/health-check").Result.StatusCode; } catch (Exception) { } } string message = httpStatusCode == HttpStatusCode.OK ? "All site pages available to crawl" : "Error on 1 or many pages on site crawl"; return new HealthCheckStatus(message) { ResultType = httpStatusCode == HttpStatusCode.OK ? StatusResultType.Success : StatusResultType.Error, Actions = new List() }; } } }
The class inherits from Umbraco.Web.HealthCheck and then overrides two methods. In our use-case we only need to provide code to override the GetStatus method.
In the method we make a simple http request to a custom controller url (e.g. https://www.mywebsite.co.uk/crawl/health-check), which crawls all our website and returns a http 200 response for no errors, or a http 500 if one or many errors are experienced.
The method then returns a Umbraco.Web.HealthCheck.HealthCheckStatus class that can include a simple custom message and either a Umbraco.Web.HealthCheck.Success or Error enum value.
Umbraco Website Up-Time Check
You can include your custom checking logic within your Health Check class, but we chose to keep ours in our MVC Controller class so we had access to the Umbraco Node tree for the site crawl.
For completeness, here is the code for our custom controller that performs the Umbraco website crawl:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Mvc; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web; using Website.Models.Crawl; namespace Website.Controllers { /// /// Crawl Controller /// public class CrawlController : BaseController { /// /// List of site Urls /// private List _siteUrls; /// /// Site Crawl Results /// /// Site Crawl Page [HttpGet] public ActionResult Index() { return View(new CrawlModel() { Results = CrawlSitePages() }); } /// /// Site Crawl Results /// /// 200 = OK, 500 = Page Issue [HttpGet] public ActionResult HealthCheck() { Dictionary<string, string> siteCrawlResults = CrawlSitePages(); var overallSiteStatus = HttpStatusCode.InternalServerError; if (siteCrawlResults.Any() && siteCrawlResults.Count(x => string.Equals(x.Value, "ok", StringComparison.CurrentCultureIgnoreCase)) == siteCrawlResults.Count) { overallSiteStatus = HttpStatusCode.OK; } return new HttpStatusCodeResult(overallSiteStatus); } /// /// Crawl Site Pages /// /// Dictionary of Results private Dictionary<string, string> CrawlSitePages() { IPublishedContent homeNode = Umbraco.ContentAtRoot().FirstOrDefault(); var crawlResults = new Dictionary<string, string>(); if (homeNode != null) { _siteUrls = new List(); _siteUrls.Add($"{App.Settings.TLD}{homeNode.Url}"); GetNextNodeUrl(homeNode); using (var httpClient = new HttpClient()) { foreach (string siteUrl in _siteUrls) { HttpResponseMessage response = null; try { response = httpClient.GetAsync(siteUrl).Result; crawlResults.Add(siteUrl, response.StatusCode.ToString()); } catch (Exception ex) { crawlResults.Add(siteUrl, $"Error: {response.StatusCode.ToString()} | Exception: {ex.Message}"); } } } } return crawlResults; } /// /// Gets Next Node Url /// ///An Umbraco Node private void GetNextNodeUrl(IPublishedContent umbracoNode) { if (umbracoNode != null) { var pageNodes = umbracoNode.Descendants().Where(x => x.Value("NoIndex", fallback: Fallback.ToDefaultValue, defaultValue: false) == false).Where(x => x.Value("HideInSitemap", fallback: Fallback.ToDefaultValue, defaultValue: false) == false); foreach (var node in pageNodes) { string urlToAdd = $"{App.Settings.TLD}{node.Url}"; if (_siteUrls.FirstOrDefault(x => string.Equals(x, urlToAdd)) == null) { _siteUrls.Add($"{App.Settings.TLD}{node.Url}"); if (node.Children.Where(x => x.Value("NoIndex", fallback: Fallback.ToDefaultValue, defaultValue: false) == false).Where(x => x.Value("HideInSitemap", fallback: Fallback.ToDefaultValue, defaultValue: false) == false).Count() > 0) { GetNextNodeUrl(node); } } } } } } }
Deploy Your Custom Health Check
Once you have created your custom Health Check class, its just a case of compiling and deploying your website and Umbraco takes care or the rest.
When you log into the Umbraco back office you will see your custom Health Check and its results. We added ours to a Custom group (via the annotation at the top of the HealthCheck class) to keep it separate from the other checks.
Hopefully you have found this article on how to create simple custom up-time health checks for your Umbraco 8 website useful, and the custom Umbraco Health Check example source code is available in our GitHub repo. You might also find these Umbraco coding examples and tutorials useful.
Leave Your Comments...