Walkthru - Creating a HealthCheck component


 
abc.png This is a step-by-step guide to creating a new custom HealthCheck component and includes instructions on getting this running in Wolfpack and reporting its data.

UPDATE Wolfpack is now on NuGet! Rob Gibbens has created the NuGet packages to support & streamline custom HealthCheck, Publisher & BuildAnalytics development. These contain just the binaries required to develop these plugins for Wolfpack...just search in the NuGet Gallery explorer within Visual Studio for "Wolfpack"......Thanks Rob, great job!


UPDATE 13th Jul 2011 There are several base classes that can be used to simplify plugin development.
  • Wolfpack.Core.Interfaces.Entities.PluginConfigBase provides a base class for your Configuration component.
  • Wolfpack.Core.Checks.HealthCheckBase<T> (Wolfpack.Core assembly, where <T> is the HealthCheck config class type). Use this for any normal HealthCheck.
  • Wolfpack.Core.Checks.StreamThresholdCheckBase<T> (Wolfpack.Core assembly, where <T> is the HealthCheck config object type). This provides some common code if your HealthCheck provides a "stream" of readings eg: you want to capture the value of something and provide an alert (failure) if the HealthCheck value breaches a user specified threshold. As an example pinging a Url HealthCheck could return the response time (the stream) and if that breached some value (say 5 seconds) then raise an alert (the site at the end of the Url is unresponsive).

NOTE Wolfpack is written with VS2010 & C# targeting the v4.0 .Net framework.

All of the following can be found in the "HelloWorldHealthCheck" project in the Source code zip. The binding and check configuration file updates are also included but commented out. The fast start version is this,
1. Get the source and unzip
2. Move the Config\Checks\helloworld.castle.config file to the Config\Checks\EveryMinute folder
3. Build the solution
4. Copy the HelloWorldHealthCheck.dll from HelloWorldHealthCheck\bin\debug into Wolfpack.Agent\bin\debug
6. Start Wolfpack from the command line with "Wolfpack.Agent.exe"

Creating a new HealthCheck

1. Create a new class library project called "HelloWorldHealthCheck"
2. Install the "Wolfpack.HealthCheck" NuGet package, this will provide the necessary interfaces and base classes.
3. Rename "Class1" to "HelloWorldCheck" and make it implement IHealthCheckPlugin (Wolfpack.Core.Interfaces namespace)
4. Add a new class called "HelloWorldCheckConfig". The name is important as a convention is used to match HealthCheck configuration with HealthChecks - THE CONFIGURATION CLASSNAME MUST BE HealthCheckClassNameConfig
5. Make "HelloWorldCheckConfig" inherit from "PluginConfigBase"
6. Add a property to "HelloWorldCheckConfig", the config class should look like...
public class HelloWorldCheckConfig : PluginConfigBase
{
    public string MyCustomSetting { get; set; }
}
7. Add a private readonly member variable of type "HelloWorldCheckConfig" called "myConfig" to "HelloWorldCheck"
private readonly HelloWorldCheckConfig myConfig;
8. Add a constructor to "HelloWorldCheck" - this should take our config class as the only parameter.
public HelloWorldCheck(HelloWorldCheckConfig config)
{
    myConfig = config;
}
9. Implement the "Status" property as an "Auto-Property". This is used by Wolfpack to track the state of a component during startup. Wolfpack will report any components that fail to initialise properly and disable them.
public Status Status { get; set; }
10. Implement the "Identity" property on "HelloWorldCheck"
public PluginDescriptor Identity
{
    get { return new PluginDescriptor
    {
        Description = "My first custom HealthCheck!",
        Name = myConfig.FriendlyId,
        // The TypeId is important - it needs to be different for
        // each health check as this allows us to positively identify
        // every health check. Use the VS Tools/Create GUID tool to
        // generate a new one.
        TypeId = new Guid("218087BB-3605-4fa5-9157-0C133674F51F")
    }; }
}
11. Implement the "Execute()" method on "HelloWorldCheck"
public void Execute()
{
    Messenger.Publish(new HealthCheckData
    {
        Identity = Identity,
        Result = true,
        Info = string.Format("MyCustomSetting:={0}", myConfig.MyCustomSetting)
    });
}
12. The "Initialise()" method on "HelloWorldCheck" should do nothing
public void Initialise()
{
    // This can be used to do any "one-time" initialisation
    // of this check - this method is called when the plugin
    // is loaded (must also be "enabled" in its configuration)
}

The finished health check should look like this,
using System;
using Wolfpack.Core.Interfaces;
using Wolfpack.Core.Interfaces.Entities;

namespace HelloWorldHealthCheck
{
    public class HelloWorldCheckConfig : PluginConfigBase
    {
        public string MyCustomSetting { get; set; }
    }

    public class HelloWorldCheck : IHealthCheckPlugin
    {
        private readonly HelloWorldCheckConfig myConfig;

        public HelloWorldCheck(HelloWorldCheckConfig config)
        {
            myConfig = config;
        }

        public void Initialise()
        {
            // This can be used to do any "one-time" initialisation
            // of this check - this method is called when the plugin
            // is loaded (must also be "enabled" in its configuration)
        }

        public Status Status { get; set; }

        public PluginDescriptor Identity
        {
            get { return new PluginDescriptor
                             {
                                 Description = "My first custom HealthCheck!",
                                 Name = myConfig.FriendlyId,
                                 // The TypeId is important - it needs to be different for
                                 // each health check as this allows us to positively identify
                                 // every health check. Use the VS Tools/Create GUID tool to
                                 // generate a new one.
                                 TypeId = new Guid("218087BB-3605-4fa5-9157-0C133674F51F")
                             }; }
        }

        public void Execute()
        {
            Messenger.Publish(new HealthCheckData
                        {
                            Identity = Identity,
                            Result = true,
                            Info = string.Format("MyCustomSetting:={0}", myConfig.MyCustomSetting)
                        });
        }

        public event PublishHandler Publish;
    }
}
12. Compile the "HelloWorldHealthCheck" project and copy the "HelloWorldHealthCheck.dll" (and .pdb) to the Wolfpack binaries folder.

Configuring the HealthCheck

1. In the Wolfpack binaries folder is a sub-folder called "Config\Checks\EveryMinute". Create a new file called "helloworld.castle.config" in this folder.

2. Copy this into the new config file...
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <components>
    <component id="MyHelloWorldCheckConfig"
	   lifestyle="singleton"
	   type="HelloWorldHealthCheck.HelloWorldCheckConfig, HelloWorldHealthCheck">
      <parameters>
        <MyCustomSetting>Hello World!!</MyCustomSetting>
        <FriendlyId>HelloWorldCheck</FriendlyId>
        <Enabled>true</Enabled>
      </parameters>
    </component>
  </components>
</configuration>
3. Start Wolfpack - your check "HelloWorldCheck" should now be running & publishing new results every 60 seconds.

4. To add another instance of your health check, just copy the helloworld.castle.config file and ensure you update the FriendlyId value...restart Wolfpack and you should now have two instances of your check running!
        <MyCustomSetting>Hello Again!!</MyCustomSetting>
        <FriendlyId>AnotherHelloWorldCheck</FriendlyId>

5. The health check is automagically bound to the scheduler based on the folder you place the health check config file in. The folder "EveryMinute" corresponds to a component named the same in the Config\scheduler.castle.config file. This means you can create a new schedule for checks simply by adding a new schedule component to scheduler.castle.config, give it a unique, meaningful name and create a folder in Config\checks named the same then just move/add health check config files to this new folder as required!

Last edited Nov 1, 2012 at 7:35 AM by jimbobdog, version 17