Automate your SharePoint farm maintenance using Health Rules

By default, SharePoint comes with a broad set of health rules and remedies which check your farm periodically. These, however, don’t always cover specific situations. For instance, your governance document may state that there may only be 10 site collections in one content database. When there are multiple administrators, it’s good practice to implement some sort of extra check, and if possible fix the error. If a newly created content database doesn’t have any limitations set, it’s good to trigger a warning or error for all of your administrators to read.

Start out by creating an empty SharePoint project. I name the solution below “CustomHealthRules”. Deploy the solution as a farm solution.

new sharepoint project customhealthrules

After the empty project is loaded, add a new class named “CheckContentdbs.cs” and inherit SPHealthAnalysisRule.

customhealthrules add new class checkcontentdbs

using Microsoft.SharePoint.Administration.Health;
using Microsoft.SharePoint.Administration;
using System.Collections.Generic;
using System.Text;

namespace CustomHealthRules
{
    class CheckContentdbs : SPHealthAnalysisRule
    {
    }
}

Because we derive from the SPHealthAnalysisRule, we override a few properties to identify our custom rule.

class CheckContentdbs : SPHealthAnalysisRule
{
    public override SPHealthCategory Category
    {
        // Categorise the health rule under configuration in the health rules definition list
        get { return SPHealthCategory.Configuration; }
    }
    public override SPHealthCheckErrorLevel ErrorLevel
    {
        // Define the health as error when the check fails
        get { return SPHealthCheckErrorLevel.Error; }
    }
    public override string Summary
    {
        // Summary of the rule
        get { return "Contentdatabases are misconfigured"; }
    }
}

Before we can make the rule pass or fail, we have to check something. Override the Check() method and identify any problems. Keep track of faulty contentdatabases in a list.

List<SPContentDatabase> faultyContentDbs = new List<SPContentDatabase>();

public override SPHealthCheckStatus Check()
{
    // loop through all web applications
    SPServiceCollection services = SPFarm.Local.Services;
    foreach (SPService curService in services)
    {
        if (curService is SPWebService)
        {
            SPWebService webService = (SPWebService)curService;
            foreach (SPWebApplication webApp in webService.WebApplications)
            {
                // for every web application, check content databases
                foreach (SPContentDatabase contentDB in webApp.ContentDatabases)
                {
                    if (contentDB.MaximumSiteCount != 10)
                    {
                        faultyContentDbs.Add(contentDB);
                    }
                }
            }
        }
    }
    if (faultyContentDbs.Count == 0)
        return SPHealthCheckStatus.Passed;
    else
        return SPHealthCheckStatus.Failed;
}

Whenever your check fails, you must give a remedy to your administrators.

public override string Remedy
{
    get { return "Set the warning and maximum site collection limit on the content database"; }
}

public override string Explanation
{
    get
    {
        if (faultyContentDbs.Count > 0)
        {
            StringBuilder sBuild = new StringBuilder();
            sBuild.Append("The following databases are incosistent:\n");
            foreach (SPContentDatabase contentDB in faultyContentDbs)
            {
                sBuild.AppendFormat("db {0} on webapp {1}\n", contentDB.Name, contentDB.WebApplication.Name);
            }
            return sBuild.ToString();
        }
        else
            return "No faulty contentdatabases have been found.";
    }
}

Finally, add some default configuration settings. You may also choose to manually configure your health rule. In that case you don’t need to override this property.

public override SPHealthAnalysisRuleAutomaticExecutionParameters AutomaticExecutionParameters
{
    get
    {
        SPHealthAnalysisRuleAutomaticExecutionParameters retval = new SPHealthAnalysisRuleAutomaticExecutionParameters();
        retval.Schedule = SPHealthCheckSchedule.Hourly;
        retval.Scope = SPHealthCheckScope.All;
        retval.ServiceType = typeof(SPTimerService);
        retval.RepairAutomatically = false;
        return retval;
    }
}

Our CheckContentdbs class file is complete. All that remains is to register the rule inside a farm feature. Add a new feature to your project, name it and add a description. You’ll see that you can’t just select your codefile in the project. Registering a health rule is slightly different than your average web part. Add a new feature EventReceiver and add the code you find on MSDN. Make sure you Resolve unadded Usings.

customhealthrules farm feature

customhealthrules feature event receiver

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    Assembly a = Assembly.GetExecutingAssembly();
    IDictionary<Type, Exception> exceptions = SPHealthAnalyzer.RegisterRules(a);

    if (exceptions != null)
    {
        string logEntry = a.FullName;
        if (exceptions.Count == 0)
        {
            logEntry += " All rules were registered.";
        }
        else
        {
            foreach (KeyValuePair<Type, Exception> pair in exceptions)
            {
                logEntry += string.Format(" Registration failed for type {0}. {1}",
                                            pair.Key, pair.Value.Message);
            }
        }
        System.Diagnostics.Trace.WriteLine(logEntry);
    }
}

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
    Assembly a = Assembly.GetExecutingAssembly();
    IDictionary<Type, Exception> exceptions = SPHealthAnalyzer.UnregisterRules(a);

    if (exceptions != null)
    {
        string logEntry = a.FullName;
        if (exceptions.Count == 0)
        {
            logEntry += " All rules were unregistered.";
        }
        else
        {
            foreach (KeyValuePair<Type, Exception> pair in exceptions)
            {
                logEntry += string.Format(" Unregistration failed for type {0}. {1}",
                                            pair.Key, pair.Value.Message);
            }
        }
        System.Diagnostics.Trace.WriteLine(logEntry);
    }
}

Deploy the solution. When you activate the farm feature in your central admin, you can check the health rules definition list (under Monitoring) and you’ll see your custom health rule is successfuly deployed!

customhealthrules registered rule

After the rule is ran, you’ll get an error in your health reports where you can check for faulty content databases.

customhealthrules rule triggered error

So what’s next? If you wish to debug your solution, remember to attach your debugger to the OWSTIMER.EXE. Health rules are timer jobs after all.

Also check the SPRepairableHealthAnalysisRule class. If you derive from this one, you can override the Repair() method where you can implement default “fixes” for your health rule.

You can also implement some Health Rule configuration for your Check() method. Think of propertybags for instance. You can put your preferred default values in the feature activated method.

Advertisements

One thought on “Automate your SharePoint farm maintenance using Health Rules

  1. Pingback: Automate your SharePoint farm maintenance using Health Rules « Unscrambling Enterprise Content Management

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s