Files
itworx-knowledge-hub-Public/src/backend/ItWorx.KnowledgeHub.Api/BackgroundServices/OperationalTelemetryBackgroundService.cs
T

42 lines
2.0 KiB
C#

using ItWorx.KnowledgeHub.Application.Operations;
namespace ItWorx.KnowledgeHub.Api.BackgroundServices;
public sealed partial class OperationalTelemetryBackgroundService(
IServiceScopeFactory scopeFactory, PlatformMetrics metrics, TimeProvider clock,
ILogger<OperationalTelemetryBackgroundService> logger) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
// Do not race initial database migration during host startup.
await Task.Delay(TimeSpan.FromSeconds(30), clock, stoppingToken);
using var scope = scopeFactory.CreateScope();
var snapshot = await scope.ServiceProvider.GetRequiredService<IOperationalTelemetryReader>()
.ReadAsync(stoppingToken);
var now = clock.GetUtcNow();
metrics.SetQueueState(snapshot.QueuedJobs, snapshot.RunningJobs, snapshot.FailedJobs,
Age(snapshot.OldestQueuedJobAt, now));
metrics.SetOperationalAges(Age(snapshot.OldestPendingIngestionAt, now),
Age(snapshot.LatestInventoryCaptureAt, now), Age(snapshot.LatestVerifiedBackupAt, now));
}
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested) { break; }
catch (Exception)
{
// Omit stale gauges after a failed read, rather than exporting old success.
metrics.ClearSnapshots();
LogReadFailed();
}
}
}
private static double? Age(DateTimeOffset? value, DateTimeOffset now) =>
value is { } time && time <= now ? (now - time).TotalSeconds : null;
[LoggerMessage(Level = LogLevel.Warning, Message = "Operationele metriekmeting mislukt; waarden blijven onbekend tot de volgende geslaagde meting.")]
private partial void LogReadFailed();
}