Skip to main content
Version: v1.1.3

Connector Health Checks

Health checks provide visibility into connector operational status, enabling proactive monitoring and automated recovery.

Built-in Health Check Integration​

Connectors implement GetHealthAsync() which returns connector health status:

var health = await connector.GetHealthAsync(ct);

if (health.IsSuccess())
{
var healthInfo = health.Value;
Console.WriteLine($"Healthy: {healthInfo.IsHealthy}");
Console.WriteLine($"State: {healthInfo.State}");
}

Health Status Values​

StatusDescription
HealthyConnector is operational and can send/receive messages
DegradedConnector is functional but experiencing issues
UnhealthyConnector cannot perform operations

ASP.NET Core Health Check Integration​

The Ratatosk.Extensions.HealthChecks package provides a ConnectorHealthCheck that automatically discovers all registered connectors and probes them through the standard ASP.NET Core health check pipeline.

Installation​

Add the Ratatosk.Extensions.HealthChecks NuGet package to your project.

Registration​

Register the health check after all connectors have been configured:

services.AddMessaging()
.AddTwilioSms(...)
.AddSendGridEmail(...);

services.AddHealthChecks()
.AddRatatoskHealthChecks();

This registers a single health check named "ratatosk" with the "messaging" tag. At check time it discovers all unnamed and named connectors via DI, probes each through GetHealthAsync(), and reports the worst status across all connectors.

Health Check Endpoint​

Configure the health check endpoint in Program.cs:

var app = builder.Build();

app.MapHealthChecks("/health");
app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("messaging")
});

app.Run();

Per-Connector Detail​

The health check result includes per-connector detail in the Data dictionary, keyed by connector type name (with the Connector suffix removed) or the named connector's registration name:

Note: By default, ASP.NET Core's MapHealthChecks middleware does not serialize HealthCheckResult.Data in the HTTP response. To expose per-connector details over HTTP, provide a custom ResponseWriter:

app.MapHealthChecks("/health/detail", new HealthCheckOptions
{
ResponseWriter = async (context, report) =>
{
var json = JsonSerializer.Serialize(new
{
status = report.Status.ToString(),
results = report.Entries.ToDictionary(
e => e.Key,
e => e.Value.Data)
});
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(json);
}
});

The per-connector data has this shape:

{
"status": "Degraded",
"results": {
"TwilioSms": {
"status": "Healthy",
"state": "Ready",
"isHealthy": true,
"issues": [],
"uptime": "01:23:45",
"lastHealthCheck": "2026-06-21T10:00:00Z"
},
"SendGridEmail": {
"status": "Degraded",
"state": "Ready",
"isHealthy": true,
"issues": ["High latency detected"],
"uptime": "01:23:45",
"lastHealthCheck": "2026-06-21T10:00:00Z"
}
}
}

Health Status Mapping​

ConnectorHealthHealthStatusOverall
IsHealthy == true, no IssuesHealthyWorst across all connectors
IsHealthy == true, has IssuesDegraded
IsHealthy == falseUnhealthy
Exception or failed OperationResultUnhealthy

Manual Health Verification​

Test connector connectivity before sending messages:

public async Task<bool> VerifyConnectorAsync(IChannelConnector connector)
{
var testResult = await connector.TestConnectionAsync(CancellationToken.None);
if (testResult.IsFailure())
return false;

var health = await connector.GetHealthAsync(CancellationToken.None);
return health.IsSuccess() && health.Value?.IsHealthy == true;
}

Health Check Implementation for Custom Connectors​

When building custom connectors, implement health checks:

public class MyConnector : ChannelConnectorBase
{
protected override Task<ConnectorHealth> GetConnectorHealthAsync(CancellationToken ct)
{
var health = new ConnectorHealth
{
State = State,
IsHealthy = State == ConnectorState.Ready,
LastHealthCheck = DateTime.UtcNow,
Uptime = DateTime.UtcNow - _initializedAt
};

if (!health.IsHealthy)
{
health.Issues.Add($"Connector is in {State} state");
}

return Task.FromResult(health);
}
}

Advanced Health Checks​

Perform actual provider connectivity tests:

protected override async Task<ConnectorHealth> GetConnectorHealthAsync(CancellationToken ct)
{
var health = new ConnectorHealth
{
State = State,
LastHealthCheck = DateTime.UtcNow
};

try
{
var response = await _httpClient.GetAsync("/health", ct);
response.EnsureSuccessStatusCode();

health.IsHealthy = true;
health.Uptime = DateTime.UtcNow - _initializedAt;
}
catch (Exception ex)
{
health.IsHealthy = false;
health.Issues.Add($"Provider health check failed: {ex.Message}");
}

return health;
}

Connector State Transitions​

Connector state affects health status:

StateIsHealthyDescription
ReadyYesOperational, can send/receive
InitializingNoStill initializing
UninitializedNoNot yet initialized
ErrorNoError state, needs recovery
ShuttingDownNoGraceful shutdown in progress
ShutdownNoConnector is shut down

Troubleshooting​

Connector Reports Unhealthy​

Check:

  1. Initialization - Was InitializeAsync() called successfully?
  2. Authentication - Are credentials valid and not expired?
  3. Network - Can the connector reach the provider API?
  4. Provider Status - Is the provider experiencing outages?

Recovery:

if (!health.IsHealthy)
{
await connector.InitializeAsync(ct);
health = await connector.GetHealthAsync(ct);
}

Health Check Endpoint Returns 503​

Causes:

  • One or more connectors are unhealthy
  • Health check timeout is too short
  • Provider API is unavailable

Solutions:

  1. Check individual connector health - Identify which connector is failing
  2. Increase health check timeout - Allow more time for provider response
  3. Implement degraded mode - Return HealthCheckResult.Degraded instead of Unhealthy

Best Practices​

DO: Implement Health Checks​

Always implement GetConnectorHealthAsync() in custom connectors - it's essential for monitoring.

DO: Test Provider Connectivity​

Don't just check internal state - verify you can actually reach the provider API.

DO: Include Diagnostic Information​

Provide useful diagnostic data in health check results:

health.Metrics["LastSuccessfulSend"] = _lastSuccessfulSend;
health.Metrics["FailedSendCount"] = _failedSendCount;

DON'T: Perform Expensive Operations​

Health checks should be lightweight and fast:

// Bad - sends actual message as health check
await SendMessageAsync(testMessage, ct);

// Good - lightweight connectivity test
await _httpClient.GetAsync("/ping", ct);

DON'T: Cache Health Status​

Always perform fresh health checks - cached status may be stale.

See Also​