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.
This sample includes a portable version of the Particular Service Platform tools. These tools are available only on Windows environments but are not necessary to run the sample.
Running the sample
Running the project will result in 3 console windows:
- 3rdPartySystem: Represents the third-party system by simulating an HTTP service running on
http:/
. At startup, the custom check is returning success, but the state can be toggled between success and failure by pressing Enter./ localhost:57789 - Monitor3rdParty: The endpoint containing the custom check. The success or failure of the third-party system is continuously written to the console.
- 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.
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);
}
}
}