Monitor third-party systems with custom checks

Component: ServiceControl CustomChecks
NuGet Package NServiceBus.CustomChecks (3.x)
Target NServiceBus Version: 7.x

When integrating with third-party systems, often messages fail when those systems are down. The Particular Platform has extensibility to enable the monitoring of third-party systems which are exposed as HTTP endpoints. This sample shows how to achieve this with custom checks.

Running the sample

Running the project will result in 3 console windows:

  1. Samples.CustomChecks.3rdPartySystem: Represents the 3rd party system by simulating an HTTP service running on http://localhost:57789. At startup, the custom check is returning success, but the state can be toggled between success and failure by pressing Enter.
  2. Samples.CustomChecks.Monitor3rdParty: The endpoint containing the custom check. The success or failure of the 3rd-party system is continuously written to the console.
  3. PlatformLauncher: Runs an in-process version of ServiceControl and ServicePulse. When the ServiceControl instance is ready, a browser window will be launched displaying the Custom Checks view in ServicePulse.

Try toggling the status of the 3rd-party system by pressing Enter in the Samples.CustomChecks.3rdPartySystem window, and watch the change in output in the Samples.CustomChecks.Monitor3rdParty window.

The status of the custom check is also reported to ServiceControl, and can be viewed in ServicePulse. In the browser window, watch on the ServicePulse Custom Checks page as the status is flipped from success to error. In addition to displaying the custom check failure on this page, an overview can also be seen on the ServicePulse Dashboard page.

The custom check

The monitoring capability implements a PeriodicCheck which calls a defined URI every time the specified interval is elapsed. When the third-party system doesn't respond in a timely fashion a CheckResult.Failed event is sent to ServiceControl.

class ThirdPartyMonitor :
    CustomCheck
{
    const string url = "http://localhost:57789";
    static ILog log = LogManager.GetLogger<ThirdPartyMonitor>();
    static HttpClient client = new HttpClient { Timeout = TimeSpan.FromSeconds(3) };

    public ThirdPartyMonitor()
        : base(
            id: $"Monitor {url}",
            category: "Monitor 3rd Party ",
            repeatAfter: TimeSpan.FromSeconds(10))
    {
    }

    public override async Task<CheckResult> PerformCheck()
    {
        try
        {
            using (var response = await client.GetAsync(url)
                .ConfigureAwait(false))
            {
                if (response.IsSuccessStatusCode)
                {
                    log.Info($"Succeeded in contacting {url}");
                    return CheckResult.Pass;
                }
                var error = $"Failed to contact '{url}'. HttpStatusCode: {response.StatusCode}";
                log.Info(error);
                return CheckResult.Failed(error);
            }
        }
        catch (Exception exception)
        {
            var error = $"Failed to contact '{url}'. Error: {exception.Message}";
            log.Info(error);
            return CheckResult.Failed(error);
        }
    }
}

Related Articles


Last modified