Table of Contents

Custom health checks

Extending health monitoring with custom health checks

Health providers perform diagnostic checks on your system (e.g., data integrity, configuration validation) and report issues. Custom health provider implementations integrate with DynamicWeb's health monitoring system, allowing centralized visibility into application health.

Base implementation

Create a class that inherits from the HealthProviderBase located in Dynamicweb.Core project.

using System.Collections.Generic;
using Dynamicweb.Configuration;
using Dynamicweb.Data;
using Dynamicweb.Diagnostics.Health;
using Dynamicweb.Extensibility.AddIns;

namespace Dynamicweb.Core.Examples.Diagnostics
{
    /// <summary>
    ///  Example of custom health provider.
    /// </summary>
    [AddInName("Custom security check")]
    [AddInIcon(UI.Icons.KnownIcon.UserCheck)]
    public sealed class CustomSecurityHealthProvider : HealthProviderBase
    {
        private readonly Dictionary<int, Check> CheckList = new()
        {
            { 1, new(1, "User emails", "Users with empty emails") },
            { 2, new(2, "Password length (Administration)", "We recommend to set the password minimum length 12") },
        };

        public override IEnumerable<Check> GetCheckList()
        {
            return CheckList.Values;
        }

        public override Check? RunCheck(int checkId)
        {
            if (CheckList.TryGetValue(checkId, out var check))
            {
                if (checkId == 1)
                    PerformEmailCheck(check);
                else if (checkId == 2)
                    PerformPasswordSecurityCheck(check);

                return check;
            }

            return null;
        }

        private static void PerformEmailCheck(Check check)
        {
            var checkDetails = new List<CheckDetail>();

            var commandBuilder = CommandBuilder.Create(@"
                SELECT au.[AccessUserUserName]
                FROM [AccessUser] au
                WHERE au.[AccessUserType] = 5
                AND (au.[AccessUserEmail] IS NULL OR au.[AccessUserEmail] = '')");
            using (var reader = Database.CreateDataReader(commandBuilder))
            {
                while (reader.Read())
                {
                    var detail = new CheckDetail
                    {
                        Key1 = "AccessUserId",
                        ObjectType = "AccessUser",
                        Value = Converter.ToString(reader.GetValue(0))
                    };

                    checkDetails.Add(detail);
                }
            }

            check.CheckWhatWasRun = commandBuilder.ToString();
            check.Count = checkDetails.Count;
            check.State = checkDetails.Count > 0 ? CheckState.Warning : CheckState.Ok;
            check.CheckDetails = checkDetails;
        }

        private static void PerformPasswordSecurityCheck(Check check)
        {
            var settingName = "/Globalsettings/Modules/Users/MinimumOfCharacters";
            var recommendedValue = 12;
            var actualValue = SystemConfiguration.Instance.GetInt32(settingName);

            check.CheckWhatWasRun = settingName;
            check.Count = actualValue;
            check.State = actualValue >= recommendedValue ? CheckState.Ok : CheckState.Error;
        }
    }
}

The following HealthProviderBase methods must be overridden:

GetCheckList()

Return all checks your provider supports:

public override IEnumerable<Check> GetCheckList()
{
    return CheckList.Values;
}

RunCheck(int checkId)

Execute the check logic for the given checkId:

public override Check RunCheck(int checkId)
{
    if (CheckList.TryGetValue(checkId, out var check))
    {
        if (checkId == 1)
            PerformEmailCheck(check);
        else if (checkId == 2)
            PerformPasswordSecurityCheck(check);

        return check;
    }

    return null;
}
To top