Getting Started
Architecture
NServiceBus
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

Monitor third-party systems with custom checks

NuGet Package: NServiceBus.CustomChecks (5.x)
Target Version: NServiceBus 9.x

External, third-party systems becoming unavailable might cause message-processing failures. The Particular Platform supports monitoring of third-party systems exposed as HTTP endpoints. This sample shows how to set up such monitoring using custom checks.

Running the sample

Running the project will result in 3 console windows:

  1. 3rdPartySystem: Represents the third-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. Monitor3rdParty: The endpoint containing the custom check. The success or failure of the third-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 third-party system by pressing Enter in the 3rdPartySystem window, and watch the change in the output of the Monitor3rdParty window.

The status of the custom check is also reported to ServiceControl, and can be viewed in ServicePulse. In the browser window, navigate to the ServicePulse Custom Checks page to see the status change from success to error. The ServicePulse Dashboard page provides the overall status of custom checks.

The custom check

The monitoring logic implements a PeriodicCheck which calls a configured URI whenever the specified interval elapses. 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 readonly ILog log = LogManager.GetLogger<ThirdPartyMonitor>();
    static readonly HttpClient client = new() { Timeout = TimeSpan.FromSeconds(3) };

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

    public override async Task<CheckResult> PerformCheck(CancellationToken cancellationToken = default)
    {
        try
        {
            using var response = await client.GetAsync(url, cancellationToken);

            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