52 lines
1.8 KiB
C#
52 lines
1.8 KiB
C#
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
|
using Microsoft.Extensions.Options;
|
|
using StellaOps.AirGap.Time.Models;
|
|
using StellaOps.AirGap.Time.Services;
|
|
|
|
namespace StellaOps.AirGap.Time.Health;
|
|
|
|
public sealed class TimeAnchorHealthCheck : IHealthCheck
|
|
{
|
|
private readonly TimeStatusService _statusService;
|
|
private readonly IOptions<AirGapOptions> _options;
|
|
private readonly TimeProvider _timeProvider;
|
|
|
|
public TimeAnchorHealthCheck(TimeStatusService statusService, IOptions<AirGapOptions> options, TimeProvider timeProvider)
|
|
{
|
|
_statusService = statusService;
|
|
_options = options;
|
|
_timeProvider = timeProvider;
|
|
}
|
|
|
|
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
|
|
{
|
|
var opts = _options.Value;
|
|
var status = await _statusService.GetStatusAsync(opts.TenantId, _timeProvider.GetUtcNow(), cancellationToken).ConfigureAwait(false);
|
|
|
|
if (status.Anchor == TimeAnchor.Unknown)
|
|
{
|
|
return HealthCheckResult.Unhealthy("time-anchor-missing");
|
|
}
|
|
|
|
if (status.Staleness.IsBreach)
|
|
{
|
|
return HealthCheckResult.Unhealthy("time-anchor-stale");
|
|
}
|
|
|
|
IReadOnlyDictionary<string, object> data = new Dictionary<string, object>
|
|
{
|
|
["anchorDigest"] = status.Anchor.TokenDigest,
|
|
["ageSeconds"] = status.Staleness.AgeSeconds,
|
|
["warningSeconds"] = status.Staleness.WarningSeconds,
|
|
["breachSeconds"] = status.Staleness.BreachSeconds
|
|
};
|
|
|
|
if (status.Staleness.IsWarning)
|
|
{
|
|
return HealthCheckResult.Degraded("time-anchor-warning", data: data);
|
|
}
|
|
|
|
return HealthCheckResult.Healthy("time-anchor-healthy", data);
|
|
}
|
|
}
|